/**
 * @file MsgMgr.h
 * @author Lost
 * @date 五月 2018
 * @brief 
 * 网络消息管理类
 */

#ifndef __MSGMGR_H__
#define __MSGMGR_H__

#include "Net.h"
#include "Singleton.h"
#include "packet.pb.h"
#include "cs_login.pb.h"

#include <google/protobuf/message.h>
#include <vector>
#include <string>

using std::vector;
using std::string;

#ifdef _WIN32
#include <hash_map>
using namespace stdext;
#else
#include <ext/hash_map>
using namespace __gnu_cxx;
#endif

/**
 * @brief 消息缓存大小
 */
#define MAX_MSG_BUFF_SIZE 16384 //16384=16*1024

#ifndef ull
#define ull unsigned long long
#endif
#ifdef __GNUC__
namespace __gnu_cxx
{
    template<>
    struct hash<unsigned long long int >
    {
        size_t operator()(unsigned long long int _x) const
        {
            return _x;
        }
    };
};
#endif


/**
 * @brief 角色状态
 */
enum ERoleState
{
    /*!< 新建状态 */
    ENM_ROLE_STATE_NEW,
    /*!< 准备状态 */
    ENM_ROLE_STATE_READY,
    /*!< 就绪状态 */
    ENM_ROLE_STATE_OK,
    /*!< 异常状态 */
    ENM_ROLE_STATE_ERROR,
};

/**
 * @brief 消息数据
 */
typedef struct stMsgData
{
    /*!< 角色ID */
    ull ullRoleID;

    /*!< 套接字 */
    int iSocket;

    /*!< 状态 */
    ERoleState eState;
}SMsgData;

/**
 * @brief 网络消息管理类
 */
class CMsgMgr : public CNet, public CSingleton<CMsgMgr>
{
public:
    CMsgMgr();
    ~CMsgMgr();
public:
    /**
     * @brief 初始化
     */
    virtual bool Init();

    /**
     * @brief 发送消息
     */
    virtual void SendPacket(const ull ullRoleID, const google::protobuf::Message &pbMessage, const comm::EnmModuleCmd iModule, const int iCmd);

    /**
     * @brief 发送消息
     */
    virtual void SendPacket(const comm::Head &pbHead, const google::protobuf::Message &pbMessage);
private:
    /**
     * @brief 收到消息事件
     */
    virtual bool OnPacket(const int iSocket, char *pBuff, int iLen);

    /**
     * @brief 收到连接事件
     */
    virtual bool OnAccept(const int iListenSocket, const int iClientSocket);

    /**
     * @brief 收到关闭事件
     */
    virtual bool OnClose(const int iSocket);
public:

    /**
     * @brief 生成cmd号
     * @note
     */
    inline int CreateCmd(comm::EnmModuleCmd eModule, int iEnmCmd) { return eModule * 10000 + iEnmCmd; }

    /**
     * @brief 创建报文头
     * @note 根据请求创建报文头
     */
    comm::Head &CreateHeadFromReq(const comm::Head &pbReqHead, int iEnmCmd, int iRet = 0, vector<string> *pRetMessage = NULL);



    /**
     * @brief 获得模块
     * @note
     */
    comm::EnmModuleCmd GetModuleFromCmd(int iCmd);

    /**
     * @brief 获得指令枚举
     * @note
     */
    inline int GetEnmCmd(int iCmd) { return iCmd % 10000; }
private:
    /*!< 收到的报文 */
    comm::Packet m_pbRecvPacket;

    /*!< 消息映射 */
    typedef hash_map<int, SMsgData> MsgMap;
    MsgMap m_mapMsg;

    /*!< 角色映射 */
    typedef hash_map<ull, SMsgData> RoleMap;
    RoleMap m_mapRole;
};


#endif // __MSGMGR_H__

